﻿#include <algorithm>
#include "EventHandler.h"

using namespace SystemTool;

// Construct the event handler
EventHandler::EventHandler() :m_bDisposed(false)
{
	Initialize();
}

// Destruct the event handler
EventHandler::~EventHandler()
{
	Destory();
}

// Initialize the event handler
void EventHandler::Initialize()
{
	ClearTable();
}

// Destory the event handler
void EventHandler::Destory()
{
	if (!GetDisposed())
	{
		SetDisposed(true);

		ClearTable();
	}
}

// Clear the map table
void EventHandler::ClearTable()
{
	m_EventMapTable.clear();

	EventMapTable().swap(m_EventMapTable);
}

// Fire event
void EventHandler::FireEvent(void* pSender, int iEventID, EventArgs* pArgs)
{
	if (pSender == NULL)
	{
		return;
	}

	if (pArgs == NULL)
	{
		return;
	}

	if (m_EventMapTable.empty())
	{
		return;
	}

	for (EventMapTable::iterator EventIter = m_EventMapTable.begin();
		EventIter != m_EventMapTable.end(); 
		++EventIter)
	{
		IDFuncMapTable IdFuncTable = EventIter->second;

		if (IdFuncTable.find(iEventID) != IdFuncTable.end())
		{
			HandlerFuncTable FuncTable = IdFuncTable[iEventID];

			for (HandlerFuncTable::iterator FuncIter = FuncTable.begin();
				FuncIter != FuncTable.end();
				++FuncIter)
			{
				EventPara Paramenter;

				Paramenter.pSender = pSender;

				Paramenter.pReceiver = EventIter->first;

				Paramenter.iEventID = iEventID;

				Paramenter.pArgs = pArgs;

				ProcessFunc pFunc = *FuncIter;

				(*pFunc)(Paramenter);
			}
		}
	}
}

// Register an object's callback to the event handler
bool EventHandler::RegisterEvent(void* pReceiver, int iEventID, ProcessFunc pHandlerFunc)
{
	if (pReceiver == NULL)
	{
		return false;
	}

	if (m_EventMapTable.find(pReceiver) != m_EventMapTable.end())
	{
		IDFuncMapTable IdFuncTable = m_EventMapTable[pReceiver];

		if (IdFuncTable.find(iEventID) != IdFuncTable.end())
		{
			HandlerFuncTable FuncTable = IdFuncTable[iEventID];

			// Wether the function is existed in the map
			HandlerFuncTable::iterator FuncIter = FuncTable.end();

			FuncIter = std::find_if(FuncTable.begin(), FuncTable.end(), [&pHandlerFunc](ProcessFunc pCurFunc) {
				
				if (*((*pHandlerFunc).target<void(EventPara&)>()) == *((*pCurFunc).target<void(EventPara&)>()))
				{
					return true;
				}
				
				return false;
			});

			// The function is existed so that we just exit
			if (FuncIter != FuncTable.end())
			{
				return false;
			}

			// Add to the func table
			FuncTable.push_back(pHandlerFunc);

			IdFuncTable[iEventID] = FuncTable;

			m_EventMapTable[pReceiver] = IdFuncTable;
		}
		else
		{
			// Add to the id-func map table
			HandlerFuncTable FuncTable;

			FuncTable.push_back(pHandlerFunc);

			IdFuncTable.insert(std::make_pair(iEventID, FuncTable));

			m_EventMapTable[pReceiver] = IdFuncTable;
		}
	}
	else
	{
		HandlerFuncTable FuncTable;

		FuncTable.push_back(pHandlerFunc);

		IDFuncMapTable IdFuncTable;

		IdFuncTable.insert(std::make_pair(iEventID, FuncTable));

		m_EventMapTable.insert(std::make_pair(pReceiver, IdFuncTable));
	}

	return true;
}

// UnRegister receiver
bool EventHandler::UnRegisterEvent(void* pReceiver)
{
	if (pReceiver == NULL)
	{
		return false;
	}

	if (m_EventMapTable.empty())
	{
		return false;
	}

	if (m_EventMapTable.find(pReceiver) != m_EventMapTable.end())
	{
		m_EventMapTable.erase(pReceiver);

		return true;
	}

	return false;
}

// UnRegister receiver
bool EventHandler::UnRegisterEvent(void* pReceiver, int iEventID)
{
	if (pReceiver == NULL)
	{
		return false;
	}

	if (m_EventMapTable.empty())
	{
		return false;
	}

	if (m_EventMapTable.find(pReceiver) != m_EventMapTable.end())
	{
		IDFuncMapTable IdFuncTable = m_EventMapTable[pReceiver];

		if (IdFuncTable.find(iEventID) != IdFuncTable.end())
		{
			IdFuncTable.erase(iEventID);

			m_EventMapTable[pReceiver] = IdFuncTable;

			return true;
		}
	}

	return false;
}

// UnRegister an object's callback from the event handler
bool EventHandler::UnRegisterEvent(void* pReceiver, int iEventID, ProcessFunc pHandlerFunc)
{
	if (pReceiver == NULL)
	{
		return false;
	}

	if (m_EventMapTable.empty())
	{
		return false;
	}

	if (m_EventMapTable.find(pReceiver) != m_EventMapTable.end())
	{
		IDFuncMapTable IdFuncTable = m_EventMapTable[pReceiver];

		if (IdFuncTable.find(iEventID) != IdFuncTable.end())
		{
			HandlerFuncTable FuncTable = IdFuncTable[iEventID];

			// Wether the function is existed in the map
			HandlerFuncTable::iterator FuncIter = FuncTable.end();

			FuncIter = std::find_if(FuncTable.begin(), FuncTable.end(), [&pHandlerFunc](ProcessFunc pCurFunc) {

				if (*((*pHandlerFunc).target<void(EventPara&)>()) == *((*pCurFunc).target<void(EventPara&)>()))
				{
					return true;
				}

				return false;
			});

			// The function is existed so that we just exit
			if (FuncIter != FuncTable.end())
			{
				FuncTable.erase(FuncIter);

				IdFuncTable[iEventID] = FuncTable;

				m_EventMapTable[pReceiver] = IdFuncTable;

				return true;
			}
		}
	}

	return false;
}

// UnRegister all eventids
bool EventHandler::UnRegisterEvent(int iEventID)
{
	if (m_EventMapTable.empty())
	{
		return false;
	}

	for (EventMapTable::iterator EventIter = m_EventMapTable.begin();
		EventIter != m_EventMapTable.end();
		++EventIter)
	{
		IDFuncMapTable IdFuncTable = EventIter->second;

		if (IdFuncTable.find(iEventID) != IdFuncTable.end())
		{
			IdFuncTable.erase(iEventID);

			return true;
		}
	}

	return false;
}

// UnRegister all eventid's func
bool EventHandler::UnRegisterEvent(int iEventID, ProcessFunc pHandlerFunc)
{
	if (m_EventMapTable.empty())
	{
		return false;
	}

	for (EventMapTable::iterator EventIter = m_EventMapTable.begin();
		EventIter != m_EventMapTable.end();
		++EventIter)
	{
		IDFuncMapTable IdFuncTable = EventIter->second;

		if (IdFuncTable.find(iEventID) != IdFuncTable.end())
		{
			HandlerFuncTable FuncTable = IdFuncTable[iEventID];

			// Wether the function is existed in the map
			HandlerFuncTable::iterator FuncIter = FuncTable.end();

			FuncIter = std::find_if(FuncTable.begin(), FuncTable.end(), [&pHandlerFunc](ProcessFunc pCurFunc) {

				if (*((*pHandlerFunc).target<void(EventPara&)>()) == *((*pCurFunc).target<void(EventPara&)>()))
				{
					return true;
				}

				return false;
			});

			// The function is existed so that we just exit
			if (FuncIter != FuncTable.end())
			{
				FuncTable.erase(FuncIter);

				IdFuncTable[iEventID] = FuncTable;

				m_EventMapTable[EventIter->first] = IdFuncTable;

				return true;
			}
		}
	}

	return false;
}

// UnRegister all funcs
bool EventHandler::UnRegisterEvent(ProcessFunc pHandlerFunc)
{
	if (pHandlerFunc == NULL)
	{
		return false;
	}

	if (m_EventMapTable.empty())
	{
		return false;
	}

	for (EventMapTable::iterator EventIter = m_EventMapTable.begin();
		EventIter != m_EventMapTable.end();
		++EventIter)
	{
		void* pReceiver = EventIter->first;

		IDFuncMapTable IdFuncTable = EventIter->second;

		for (IDFuncMapTable::iterator IDFuncIter = IdFuncTable.begin();
			IDFuncIter != IdFuncTable.end();
			++IDFuncIter)
		{
			int iEventID = IDFuncIter->first;

			HandlerFuncTable FuncTable = IDFuncIter->second;

			for (HandlerFuncTable::iterator FuncIter = FuncTable.begin();
				FuncIter != FuncTable.end();)
			{
				ProcessFunc pFunc = *FuncIter;

				if (*((*pHandlerFunc).target<void(EventPara&)>()) == *((*pFunc).target<void(EventPara&)>()))
				{
					FuncIter = FuncTable.erase(FuncIter);

					IdFuncTable[iEventID] = FuncTable;

					m_EventMapTable[pReceiver] = IdFuncTable;

					break;
				}
			}
		}
	}

	return true;
}
